﻿using Microsoft.EntityFrameworkCore; // 引入 EF Core 的异步扩展方法
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using CodeSystem.Model;

namespace CodeSystem.BLL.Base
{
    /// <summary>
    /// 业务逻辑层基础类，提供通用的 CRUD 操作。
    /// </summary>
    /// <typeparam name="T">实体类类型，必须继承自 BaseModel。</typeparam>
    /// <typeparam name="Y">业务逻辑层类型，用于日志记录。</typeparam>
    public class BaseBLL<T, Y> where T : BaseModel
    {
        // 数据库上下文实例，用于与数据库进行交互
        protected readonly WuYeDbContext _db;

        // 日志记录器实例，用于记录日志信息
        protected readonly ILogger<Y> _logger;

        // 缓存主键信息和表达式树的字典，提升性能
        private static readonly ConcurrentDictionary<Type, (PropertyInfo PkProp, Func<object, Expression<Func<T, bool>>> ExpressionBuilder)> _keyCache = new();

        /// <summary>
        /// 构造函数，初始化数据库上下文和日志记录器。
        /// </summary>
        /// <param name="db">数据库上下文实例。</param>
        /// <param name="logger">日志记录器实例。</param>
        public BaseBLL(WuYeDbContext db, ILogger<Y> logger)
        {
            _db = db ?? throw new ArgumentNullException(nameof(db));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 获取所有数据。
        /// </summary>
        /// <returns>返回所有数据的查询集合。</returns>
        public virtual IQueryable<T> GetAllList() => _db.Set<T>();

        /// <summary>
        /// 异步获取所有数据。
        /// </summary>
        /// <returns>返回所有数据的列表。</returns>
        public virtual async Task<List<T>> GetAllListAsync()
        {
            return await _db.Set<T>().ToListAsync();
        }

        /// <summary>
        /// 分页获取数据。
        /// </summary>
        /// <param name="pageIndex">页码（从 1 开始）。</param>
        /// <param name="pageSize">每页的数据条数。</param>
        /// <returns>返回分页后的数据查询集合。</returns>
        public virtual IQueryable<T> GetAllList(int pageIndex, int pageSize)
        {
            if (pageIndex < 1) throw new ArgumentOutOfRangeException(nameof(pageIndex), "页码必须大于 0");
            if (pageSize < 1) throw new ArgumentOutOfRangeException(nameof(pageSize), "每页条数必须大于 0");

            return GetAllList().Skip((pageIndex - 1) * pageSize).Take(pageSize);
        }

        /// <summary>
        /// 异步分页获取数据。
        /// </summary>
        /// <param name="pageIndex">页码（从 1 开始）。</param>
        /// <param name="pageSize">每页的数据条数。</param>
        /// <returns>返回分页后的数据列表。</returns>
        public virtual async Task<List<T>> GetAllListAsync(int pageIndex, int pageSize)
        {
            if (pageIndex < 1) throw new ArgumentOutOfRangeException(nameof(pageIndex), "页码必须大于 0");
            if (pageSize < 1) throw new ArgumentOutOfRangeException(nameof(pageSize), "每页条数必须大于 0");

            return await _db.Set<T>()
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize)
                .ToListAsync();
        }

        /// <summary>
        /// 获取所有数据的条数。
        /// </summary>
        /// <returns>返回数据的总条数。</returns>
        public virtual long Count() => GetAllList().LongCount();

        /// <summary>
        /// 异步获取所有数据的条数。
        /// </summary>
        /// <returns>返回数据的总条数。</returns>
        public virtual async Task<long> CountAsync()
        {
            return await _db.Set<T>().LongCountAsync();
        }

        /// <summary>
        /// 添加实体到数据库。
        /// </summary>
        /// <param name="entity">要添加的实体对象。</param>
        /// <returns>返回操作是否成功。</returns>
        public virtual bool Add(T entity)
        {
            if (entity == null) throw new ArgumentNullException(nameof(entity));

            _db.Set<T>().Add(entity);
            return _db.SaveChanges() > 0;
        }

        /// <summary>
        /// 异步添加实体到数据库。
        /// </summary>
        /// <param name="entity">要添加的实体对象。</param>
        /// <returns>返回操作是否成功。</returns>
        public virtual async Task<bool> AddAsync(T entity)
        {
            if (entity == null) throw new ArgumentNullException(nameof(entity));

            await _db.Set<T>().AddAsync(entity);
            return await _db.SaveChangesAsync() > 0;
        }

        /// <summary>
        /// 根据条件获取实体。
        /// </summary>
        /// <param name="predicate">查询条件。</param>
        /// <returns>返回符合条件的实体对象，如果未找到则返回 null。</returns>
        public virtual T? Get(Expression<Func<T, bool>> predicate)
        {
            // 使用缓存的表达式树查询
            return _db.Set<T>().FirstOrDefault(predicate);
        }

        /// <summary>
        /// 异步根据条件获取实体。
        /// </summary>
        /// <param name="predicate">查询条件。</param>
        /// <returns>返回符合条件的实体对象，如果未找到则返回 null。</returns>
        public virtual async Task<T?> GetAsync(Expression<Func<T, bool>> predicate)
        {
            // 使用缓存的表达式树查询
            return await _db.Set<T>().FirstOrDefaultAsync(predicate);
        }

        /// <summary>
        /// 根据条件获取实体集合
        /// </summary>
        /// <param name="predicate">查询条件。</param>
        /// <returns>返回符合条件的实体对象，如果未找到则返回 null。</returns>
        public virtual IQueryable<T> GetList(Expression<Func<T, bool>> predicate)
        {
            // 使用缓存的表达式树查询
            return _db.Set<T>().Where(predicate);
        }

        /// <summary>
        /// 异步根据条件获取实体集合
        /// </summary>
        /// <param name="predicate">查询条件。</param>
        /// <returns>返回符合条件的实体对象，如果未找到则返回 null。</returns>
        public virtual async Task<List<T>> GetListAsync(Expression<Func<T, bool>> predicate)
        {
            // 使用缓存的表达式树查询
            return await _db.Set<T>().Where(predicate).ToListAsync();
        }

        /// <summary>
        /// 更新实体到数据库。
        /// </summary>
        /// <param name="entity">要更新的实体对象。</param>
        /// <returns>返回操作是否成功。</returns>
        public virtual bool Update(T entity)
        {
            if (entity == null) throw new ArgumentNullException(nameof(entity));

            _db.Set<T>().Update(entity);
            return _db.SaveChanges() > 0;
        }

        /// <summary>
        /// 异步更新实体到数据库。
        /// </summary>
        /// <param name="entity">要更新的实体对象。</param>
        /// <returns>返回操作是否成功。</returns>
        public virtual async Task<bool> UpdateAsync(T entity)
        {
            if (entity == null) throw new ArgumentNullException(nameof(entity));

            _db.Set<T>().Update(entity);
            return await _db.SaveChangesAsync() > 0;
        }

        /// <summary>
        /// 根据条件删除实体。
        /// </summary>
        /// <param name="predicate">删除条件。</param>
        /// <returns>返回操作是否成功。</returns>
        public virtual bool Delete(Expression<Func<T, bool>> predicate)
        {
            var entity = Get(predicate);
            if (entity == null) return false;

            _db.Set<T>().Remove(entity);
            return _db.SaveChanges() > 0;
        }

        /// <summary>
        /// 异步根据条件删除实体。
        /// </summary>
        /// <param name="predicate">删除条件。</param>
        /// <returns>返回操作是否成功。</returns>
        public virtual async Task<bool> DeleteAsync(Expression<Func<T, bool>> predicate)
        {
            var entity = await GetAsync(predicate);
            if (entity == null) return false;

            _db.Set<T>().Remove(entity);
            return await _db.SaveChangesAsync() > 0;
        }

        /// <summary>
        /// 判断是否存在满足条件的实体。
        /// </summary>
        /// <param name="predicate">查询条件。</param>
        /// <returns>返回是否存在满足条件的实体。</returns>
        public virtual bool IsExist(Expression<Func<T, bool>> predicate)
        {
            return _db.Set<T>().Any(predicate);
        }

        /// <summary>
        /// 异步判断是否存在满足条件的实体。
        /// </summary>
        /// <param name="predicate">查询条件。</param>
        /// <returns>返回是否存在满足条件的实体。</returns>
        public virtual async Task<bool> IsExistAsync(Expression<Func<T, bool>> predicate)
        {
            return await _db.Set<T>().AnyAsync(predicate);
        }
    }
}